<template>
  <mxp-popup ref="popupRef" model="bottom" :showToolbar="false" :offsetBottom="options.offset" :zIndex="options.zIndex" @hide="onHide" @show="onShow">
    <view style="transition: height 0.3s" :style="{ height: pickerState ? '0px' : '60px' }">
      <mxp-toolbar
        v-if="!pickerState"
        v-bind="options.toolbarOptions"
        :title="options.title"
        :confirmColor="options.themeColor"
        @cancel="cancelTap"
        @confirm="submitTap"
      ></mxp-toolbar>
    </view>
    <mxp-line v-if="!pickerState && showLine"></mxp-line>
    <mxp-calendar-view :selected="options.selected" v-bind="options" @pickerState="pickerStateFun" @change="change"></mxp-calendar-view>
    <template #root>
      <mxp-toast ref="toastRef" offsetTop="80px"></mxp-toast>
    </template>
  </mxp-popup>
</template>

<script lang="ts" setup>
  import { type CSSProperties, ref } from 'vue';
  import MxpToolbar, { type $ToolbarProps } from '../mxp-toolbar/mxp-toolbar.vue';
  import MxpLine from '../mxp-line/mxp-line.vue';
  import MxpToast from '../mxp-toast/mxp-toast.vue';
  import MxpPopup from '../mxp-popup/mxp-popup.vue';
  import { removeObjectEmpty } from '../mxp-tool/utils/obj';
  import MxpCalendarView, { type $CalendarViewResult, type $CalendarViewSelected } from '@/mxp-ui/mxp-calendar-view/mxp-calendar-view.vue';
  import type { $BadgeProps } from '../mxp-badge/mxp-badge.vue';
  import type { $AllColorStr, $SizeUnitStr } from '@/mxp-ui/mxp-tool/types/interface';
  import mxpGetSysInfoStore from '../mxp-tool/store/mxp-store-sys-info';
  export type $CalendarPopupSelected = $CalendarViewSelected;
  export type $CalendarPopupResult = $CalendarViewResult;
  export interface $CalendarPopupProps {
    /** 每一天高度 */
    dayHeight?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** 自定义当前时间 */
    date?: string[] | string; // eslint-disable-line vue/no-unused-properties
    /** 日历类型 */
    type?: 'month' | 'week'; // eslint-disable-line vue/no-unused-properties
    /** 日期选择模式 */
    mode?: 'multiple' | 'range' | 'single'; // eslint-disable-line vue/no-unused-properties
    /** 是否使用默认日期  */
    useToday?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 徽标的配置  */
    badgeOptions?: $BadgeProps; // eslint-disable-line vue/no-unused-properties
    /** 是否使用折叠功能 */
    fold?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 背景颜色 */
    background?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 主题色 */
    themeColor?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 日期字体颜色 */
    dayColor?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 日期字体大小 */
    daySize?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** 日期字体加粗 */
    dayBold?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 农历字体颜色 */
    lunarColor?: $AllColorStr; // eslint-disable-line vue/no-unused-properties
    /** 农历字体大小 */
    lunarSize?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** mode=range时，第一个日期底部的提示文字 */
    startText?: string; // eslint-disable-line vue/no-unused-properties
    /** mode=range时，最后一个日期底部的提示文字 */
    endText?: string; // eslint-disable-line vue/no-unused-properties
    /** 日历以周几开始 */
    startWeek?: 'mon' | 'sun'; // eslint-disable-line vue/no-unused-properties
    /** 打点，期待格式[{date: '2019-06-27', info: '签到', data: { custom: '自定义信息', name: '自定义消息头',xxx:xxx... }}] */
    selected?: $CalendarViewSelected[]; // eslint-disable-line vue/no-unused-properties
    /** 是否显示农历 */
    lunar?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 日期选择范围-开始日期 */
    startDate?: string; // eslint-disable-line vue/no-unused-properties
    /** 日期选择范围-结束日期 */
    endDate?: string; // eslint-disable-line vue/no-unused-properties
    /** 允许日期选择范围内重选结束日期 */
    rangeEndRepick?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 允许日期选择范围起始日期为同一天 */
    rangeSameDay?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 允许日期选择范围内遇到打点禁用日期进行截断 */
    rangeHaveDisableTruncation?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 月份仅显示当月日期 */
    monthShowCurrentMonth?: boolean; // eslint-disable-line vue/no-unused-properties
    /** mode==='multiple' 时最少选择几个日期 */
    minQuantity?: number;
    /** mode==='multiple' 时最多选择几个日期 */
    maxQuantity?: number;
    /** 滑动切换模式，可选值 horizontal:横向; vertical:纵向; none:不使用滑动切换 */
    slideSwitchMode?: 'horizontal' | 'none' | 'vertical'; // eslint-disable-line vue/no-unused-properties
    /** 是否显示月份为背景 */
    showMonth?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 禁止点击日历 */
    disabled?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 周几的文字 默认：[ '周一', '周二', '周三', '周四', '周五', '周六','周日'] */
    weekText?: [string, string, string, string, string, string, string]; // eslint-disable-line vue/no-unused-properties
    /** 周几文字的样式 */
    weekTextStyle?: CSSProperties; // eslint-disable-line vue/no-unused-properties
    /** 是否显示线条 */
    showLine?: boolean;
    /** 自定义的样式属性 */
    calendarStyle?: CSSProperties; // eslint-disable-line vue/no-unused-properties
    /** 底部偏移量 */
    offset?: $SizeUnitStr; // eslint-disable-line vue/no-unused-properties
    /** 层级 */
    zIndex?: number;
    /** 是否显示透明遮罩以防止触摸穿透 */
    mask?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 是否可以点击遮罩关闭 */
    maskClose?: boolean; // eslint-disable-line vue/no-unused-properties
    /** 标题 */
    title?: string; // eslint-disable-line vue/no-unused-properties
    /** 顶部工具栏配置项 */
    toolbarOptions?: $ToolbarProps; // eslint-disable-line vue/no-unused-properties
  }

  export type $CallBack = {
    confirm?: (data: $CalendarViewResult) => void;
    change?: (data: $CalendarViewResult) => void;
  };
  export type $Options = $CalendarPopupProps & $CallBack;

  defineOptions({
    name: 'mxp-calendar-popup',
  });

  const props = withDefaults(defineProps<$CalendarPopupProps>(), {
    offset: '0px',
    dayHeight: '60px',
    date: '',
    type: 'month',
    mode: 'range',
    useToday: undefined,
    badgeOptions: undefined,
    fold: true,
    background: '#ffffff',
    themeColor: '#3c9cff',
    dayColor: '#313131',
    daySize: '18px',
    dayBold: false,
    lunarColor: '#313131',
    lunarSize: '12px',
    startText: '开始',
    endText: '结束',
    startWeek: 'mon',
    selected: () => [],
    lunar: true,
    startDate: '',
    endDate: '',
    rangeEndRepick: false,
    rangeSameDay: false,
    rangeHaveDisableTruncation: false,
    monthShowCurrentMonth: false,
    slideSwitchMode: 'horizontal',
    showMonth: true,
    disabled: false,
    weekTextStyle: () => ({}),
    weekText: () => ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
    calendarStyle: () => ({}),
    cusClass: '',
    showLine: true,
    mask: true,
    maskClose: true,
    zIndex: 888,
    minQuantity: 1,
    maxQuantity: Number.MAX_VALUE,
    title: '请选择日期',
    toolbarOptions: () => ({}),
  });
  const emits = defineEmits<{
    (e: 'show'): void;
    (e: 'hide', type: 'button' | 'confirm' | 'mask' | 'rest'): void;
  }>();

  /** 默认数据 */
  const options = ref<$Options>({});
  const maskStyle = ref<CSSProperties>({});
  const pickerState = ref(false);
  const popupRef = ref<InstanceType<typeof MxpPopup> | null>(null);
  const toastRef = ref<InstanceType<typeof MxpToast> | null>(null);
  const select = ref<$CalendarViewResult | undefined>(undefined);
  /** 取消 */
  function cancelTap() {
    hide();
  }

  /** 监听隐藏 */
  function onHide(type: 'button' | 'confirm' | 'mask' | 'rest') {
    emits('hide', type);
  }
  /** 监听显示 */
  function onShow() {
    emits('show');
  }
  /**
   * 确定
   */
  function submitTap() {
    if (options.value.mode === 'range') {
      if (select.value && select.value.range.after && select.value.range.before) {
        typeof options.value.confirm === 'function' && options.value.confirm(select.value);
        hide('confirm');
      } else {
        toastRef.value?.showError('请选择开始和结束时间');
      }
    } else if (options.value.mode === 'multiple') {
      const len = select.value?.multiple.length || -1;
      if (select.value && len <= props.maxQuantity && len >= props.minQuantity) {
        typeof options.value.confirm === 'function' && options.value.confirm(select.value);
        hide('confirm');
      } else if (select.value) {
        toastRef.value?.showError('请选择日期');
      } else if (len > props.minQuantity) {
        toastRef.value?.showError(`最多选择${props.maxQuantity}个日期`);
      } else if (len < props.minQuantity) {
        toastRef.value?.showError(`最少选择${props.minQuantity}个日期`);
      }
    } else {
      if (select.value && select.value.fulldate) {
        typeof options.value.confirm === 'function' && options.value.confirm(select.value);
        hide('confirm');
      } else {
        toastRef.value?.showError('请选择日期');
      }
    }
  }

  /** 监听改变 */
  function change(res: $CalendarViewResult) {
    select.value = res;
    typeof options.value.change === 'function' && options.value.change(res);
  }

  /**
   * 确定
   */
  function pickerStateFun(state: boolean) {
    pickerState.value = state;
  }

  /**
   * 显示
   */
  function show(param: $Options = {}) {
    select.value = undefined;
    options.value = { ...props, ...removeObjectEmpty(param) };
    const sys = mxpGetSysInfoStore().getSysInfo();
    maskStyle.value = {
      height: `${sys.value.windowHeight}px`,
      width: `${sys.value.windowWidth}px`,
      bottom: '0px',
      left: '0px',
      zIndex: props.zIndex + 1,
      position: 'fixed',
      backgroundColor: 'rgba(0, 0, 0, 0.3)',
    };
    popupRef.value?.show();
  }

  /** 隐藏 */
  function hide(type?: 'button' | 'confirm' | 'mask' | 'rest') {
    popupRef.value?.hide(type);
  }

  defineExpose({
    /** 显示 */
    show,
    /** 隐藏 */
    hide,
  });
</script>
